# Home Automation Control System (HACS version 0.1)
# Name: Colin Lobo
# Email: lobocjd@gmail.com
# Web: www.cas.mcmaster.ca/~lobocj

# Purpose
# This program was designed as part of a personal project on
# home automation (http://en.wikipedia.org/wiki/Home_automation)

# Program Description
# This program retrieves data (textfile) from a remote server,
# packages this data into a packet and finally sends this packet
# to an Arduino which is connected via USB.

# Notes:
# Most of the retrieve_status() function can be found in the SOURCES link.

# SOURCES: http://docs.python.org/release/3.1.5/howto/urllib2.html


import urllib.request #extensible library for opening URLs and retrieving data
import socket #socket library to prevent hanging
from time import sleep #time library to check request status from server every time_check seconds
import serial #pySerial library for serial communication to Arduino

time_check = 1 #check server every time_check second
URL = 'http://www.cas.mcmaster.ca/~lobocj/php/led_status.txt' #location of textfile
timeout = 10 #timeout in seconds
socket.setdefaulttimeout(timeout) #define how long socket should wait for a response before timing out
baudrate = 9600 #must be same as Arduino side
serialport = 'COM3' #port Arduino is connected to

#This function requests and retrieves data from server textfile
def retrieve_status():
    req = urllib.request.Request(URL)
    try: response = urllib.request.urlopen(req)
    except urllib.error.URLError as e:
        print(e.reason)
    ledstate_contents = response.read() #return entire file contents as byte object
    return ledstate_contents

#This creates a packet to send to Arduino
def packet(ledstate_contents):
    packet = '1' #header of packet (SOH - Start of heading in ASCII)
    data = str(ledstate_contents,"utf-8") #decode byte string and turn into character (unicode) string
    packet += data
    packet_length = len(packet)
    return packet, packet_length

def main():
    ser = serial.Serial(serialport,baudrate) #setup serial connection
    sleep(5) #this is necessary since Arduino 'reboots' when serial connection is established, so we give it 5 seconds to 'reboot' before sending

    #Below code loops forever
    while True:
        ledstate_contents = retrieve_status()
        txpacket, txlength = packet(ledstate_contents)
        ser.write(bytes(txpacket, 'ascii')) #encode packet and send
        sleep(time_check)
        

# Below code detects whether this module (.py file) is being
# imported into another module or run directly. When a python
# program runs, a preset variable __name__ takes the value of
# "main" if the module is run directly. So in essense, anything in
# main() in this module will not run if this module is imported.

if __name__ == "__main__":
    main()

